﻿using NPOI.OpenXmlFormats.Wordprocessing;
using NPOI.XWPF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace CoreMembers.FileHelp
{
    public static class NPOIHelpW
    {
        #region word封装
        /// <summary>
        /// 设置行的高度
        /// </summary>
        /// <param name="row"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static XWPFTableRow SetRowHeight(this XWPFTableRow row, int height)
        {
            row.Height = height;
            return row;
        }
        /// <summary>
        /// 设置表格宽度
        /// </summary>
        /// <param name="table"></param>
        /// <param name="width"></param>
        /// <returns></returns>
        public static XWPFTable SetTableWidth(this XWPFTable table, int width)
        {
            table.Width = width;
            return table;
        }
        /// <summary>
        /// 创建表格，并设置列宽
        /// </summary>
        /// <param name="document"></param>
        /// <param name="rows"></param>
        /// <param name="columnWidths"></param>
        /// <returns></returns>
        public static XWPFTable CreateTableAndSetColumnWidth(this XWPFDocument document,
            int rows, params ulong[] columnWidths)
        {
            var table = document.CreateTable(rows, columnWidths.Length);
            for (int i = 0; i < columnWidths.Length; i++)
            {
                table.SetColumnWidth(i, columnWidths[i]);
            }
            return table;
        }

        /// <summary>
        /// 合并指定行的指定单元格
        /// </summary>
        /// <param name="table"></param>
        /// <param name="rowIndex"></param>
        /// <param name="cellStartIndex"></param>
        /// <param name="cellEndIndex"></param>
        /// <returns></returns>
        public static XWPFTable MergeRowCells(this XWPFTable table, int rowIndex, int cellStartIndex, int cellEndIndex)
        {
            var row = table.GetRow(rowIndex);
            if (row == null) throw new ArgumentException("行索引超过了已有的行");
            row.MergeCells(cellStartIndex, cellEndIndex);
            return table;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="table"></param>
        /// <param name="rowStart"></param>
        /// <param name="colStart"></param>
        /// <param name="rowEnd"></param>
        /// <param name="colEnd"></param>
        /// <returns></returns>
        public static XWPFTable MergeCells(this XWPFTable table,int rowStart,int colStart,int rowEnd,int colEnd)
        {
            table.MergeCells(rowStart, colStart,rowEnd,colEnd);
            return table;
        }
        /// <summary>
        /// 设置表格的表头内容
        /// </summary>
        /// <param name="table"></param>
        /// <param name="paragraphAlign"></param>
        /// <param name="textPosition"></param>
        /// <param name="isBold"></param>
        /// <param name="fontSize"></param>
        /// <param name="titles"></param>
        public static XWPFTable SetTableHeadTitle(this XWPFTable table,
            ParagraphAlignment paragraphAlign,
            int textPosition = 24,
            bool isBold = false,
            int fontSize = 10,
            params string[] titles
            )
        {
            if (titles.Any())
            {
                for (int i = 0; i < titles.Length; i++)
                {
                    table.SetTableParagraph(0, i, titles[i], paragraphAlign, textPosition, isBold, fontSize);
                }
            }
            return table;
        }


        /// <summary>
        /// 设置指定行的段落文本
        /// </summary>
        /// <param name="document"></param>
        /// <param name="docPoint"></param>
        /// <param name="fillContent"></param>
        /// <param name="isBold"></param>
        /// <param name="fontSize"></param>
        /// <param name="fontFamily"></param>
        /// <param name="paragraphAlign"></param>
        /// <param name="isStatement"></param>
        /// <param name="secondFillContent"></param>
        /// <param name="fontColor"></param>
        /// <param name="isItalic"></param>
        /// <param name="position"></param>
        public static void SetDocumentParagraph(this XWPFDocument document,
            int docPoint,
            string fillContent,
            bool isBold,
            int fontSize,
            string fontFamily,
            ParagraphAlignment paragraphAlign,
            bool isStatement = false,
            string secondFillContent = "",
            string fontColor = "000000",
            bool isItalic = false,
            int position = 35
            )
        {
            XWPFParagraph paragraph = document.CreateParagraph();//创建段落对象
            paragraph.Alignment = paragraphAlign;//文字显示位置,段落排列（左对齐，居中，右对齐）


            XWPFRun xwpfRun = paragraph.CreateRun();//创建段落文本对象
            xwpfRun.IsBold = isBold;//文字加粗
            xwpfRun.SetText(fillContent);//填充内容
            xwpfRun.FontSize = fontSize;//设置文字大小
            xwpfRun.IsItalic = isItalic;//是否设置斜体（字体倾斜）
            xwpfRun.SetColor(fontColor);//设置字体颜色--十六进制
            xwpfRun.SetFontFamily(fontFamily, FontCharRange.None); //设置标题样式如：（微软雅黑，隶书，楷体）根据自己的需求而定
            xwpfRun.SetTextPosition(position);// 设置行间距
            if (isStatement)
            {
                XWPFRun secondXwpfRun = paragraph.CreateRun();//创建段落文本对象
                secondXwpfRun.IsBold = isBold;//文字加粗
                secondXwpfRun.SetText(secondFillContent);//填充内容
                secondXwpfRun.FontSize = fontSize;//设置文字大小
                secondXwpfRun.IsItalic = isItalic;//是否设置斜体（字体倾斜）
                secondXwpfRun.SetColor(fontColor);//设置字体颜色--十六进制
                secondXwpfRun.SetTextPosition(position);// 设置行间距
                secondXwpfRun.SetFontFamily(fontFamily, FontCharRange.None); //设置标题样式如：（微软雅黑，隶书，楷体）根据自己的需
            }
            document.SetParagraph(paragraph, docPoint);
        }
        /// <summary>
        /// 设置table 单元格的段落
        /// </summary>
        /// <param name="table"></param>
        /// <param name="rowIndex"></param>
        /// <param name="cellIndex"></param>
        /// <param name="fillContent"></param>
        /// <param name="paragraphAlign"></param>
        /// <param name="textPosition"></param>
        /// <param name="isBold"></param>
        /// <param name="fontSize"></param>
        /// <param name="fontColor"></param>
        /// <param name="isItalic"></param>
        public static XWPFTable SetTableParagraph(
            this XWPFTable table,
            int rowIndex,
            int cellIndex,
            string fillContent,
            ParagraphAlignment paragraphAlign,
            int textPosition = 24,
            bool isBold = false,
            int fontSize = 10,
            string fontColor = "000000",
            bool isItalic = false
            )
        {
            var para = new CT_P();
            //设置单元格文本对齐
            para.AddNewPPr().AddNewTextAlignment();
            XWPFParagraph paragraph = new XWPFParagraph(para, table.Body);//创建表格中的段落对象
            paragraph.Alignment = paragraphAlign;//文字显示位置,段落排列（左对齐，居中，右对齐）
            paragraph.FontAlignment = Convert.ToInt32(ParagraphAlignment.CENTER);//字体在单元格内显示位置与 paragraph.Alignment效果相似
            XWPFRun xwpfRun = paragraph.CreateRun();//创建段落文本对象
            xwpfRun.SetText(fillContent);
            xwpfRun.FontSize = fontSize;//字体大小
            xwpfRun.SetColor(fontColor);//设置字体颜色--十六进制
            xwpfRun.IsItalic = isItalic;//是否设置斜体（字体倾斜）
            xwpfRun.IsBold = isBold;//是否加粗
            xwpfRun.SetFontFamily("宋体", FontCharRange.None);//设置字体（如：微软雅黑,华文楷体,宋体）
            xwpfRun.SetTextPosition(textPosition);//设置文本位置（设置两行之间的行间），从而实现table的高度设置效果 
            table.GetRow(rowIndex).GetCell(cellIndex)
                .SetParagraph(paragraph);
            return table;
        }


        /// <summary>
        /// 设置页边距
        /// </summary>
        /// <param name="document"></param>
        /// <param name="left"></param>
        /// <param name="top"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        public static XWPFDocument SetDocumentMargin(this XWPFDocument document,
            string left,//左边距
            string top,// 上边距
            string right,
            string bottom
            )
        {
            CT_PageMar mar = new CT_PageMar();
            CT_SectPr sectPr = new CT_SectPr();
            sectPr.pgMar = mar;
            mar.bottom = bottom;
            mar.top = top;
            mar.left = ulong.Parse(left);
            mar.right = ulong.Parse(right);
            document.Document.body.sectPr = sectPr;
            return document;
            //}

        }
        #endregion
        #region 测试模板
        public static string Test()
        {
            string result = "";
            try
            {
                string currentDate = DateTime.Now.ToString("yyyyMMdd");
                string checkTime = DateTime.Now.ToString("yyyy年MM月dd日");//检查时间
                string workFileName = checkTime + "2021年7月用料需求单";
                string fileName = string.Format("{0}.docx", workFileName, System.Text.Encoding.UTF8);
                //通过使用文件流，创建文件流对象，向文件流中写入内容，并保存为Word文档格式
                using (var stream = new FileStream(Path.Combine("D:\\", fileName), FileMode.Create, FileAccess.Write))
                {
                    //创建document文档对象对象实例
                    XWPFDocument document = new XWPFDocument();
                    var tableWidth = 5000;

                    //文本标题
                    document.SetDocumentParagraph(0, workFileName, true, 14, "宋体", ParagraphAlignment.CENTER, position: 40);
                    //TODO:这里一行需要显示两个文本
                    var docString1 = $"编号：20190927101120445887";
                    var docString2 = $"                                           计划时间：{checkTime}";
                    document.SetDocumentParagraph(1, docString1, true, 10, "宋体", ParagraphAlignment.LEFT, true, $"{docString2}");

                    // 创建一个 3行 4列的表格
                    document
                        .CreateTableAndSetColumnWidth(3, 1000, 1500, 1000, 1500)
                        .SetTableWidth(tableWidth)
                        .MergeRowCells(0, 1, 3)
                        .SetTableParagraph(0, 0, "计划名称", ParagraphAlignment.CENTER, 35, true)
                        .SetTableParagraph(0, 1, "天津地铁十一号线用料需求计划单", ParagraphAlignment.CENTER, 35, true)
                        .SetTableParagraph(1, 0, "提交人", ParagraphAlignment.CENTER, 35, true)
                        .SetTableParagraph(1, 1, "张麻子", ParagraphAlignment.CENTER, 35, false)
                        .SetTableParagraph(1, 2, "提交时间", ParagraphAlignment.CENTER, 50, true)
                        .SetTableParagraph(1, 3, "2021-08-10 12:00:00", ParagraphAlignment.CENTER, 35, false)
                        .MergeRowCells(2, 0, 3)// 合并单元格
                        .SetTableParagraph(2, 0, "材料清单", ParagraphAlignment.CENTER, 35, true, 15);

                    // 创建材料清单的表格
                    var headTitles = new string[] { "序号", "材料类别", "材料名称", "规格型号", "计量单位", "需求数量" };
                    var twoTable = document
                        .CreateTableAndSetColumnWidth(8, 200, 800, 1500, 1000, 750, 750)
                        .SetTableHeadTitle(ParagraphAlignment.CENTER, 24, true, titles: headTitles)
                        .MergeRowCells(7, 0, 5)
                        .MergeCells(1,2,3,4)
                        .SetTableParagraph(7, 0, "审批结果", ParagraphAlignment.CENTER, 50, true, 15);
                    for (int i = 1; i < 7; i++)
                    {
                        for (int j = 0; j < headTitles.Length; j++)
                        {
                            twoTable.SetTableParagraph(i, j, headTitles[j].ToString() + i, ParagraphAlignment.CENTER, 24, false);
                        }
                    }

                    // 创建第三个表格
                    var threeTableHeadTitle = new string[] { "序号", "审批意见", "审批状态", "审批人", "审批时间" };
                    var threeTable = document.CreateTableAndSetColumnWidth(5, 200, 2400, 1000, 1000, 1000)
                        .SetTableWidth(tableWidth)
                        .SetTableHeadTitle(ParagraphAlignment.CENTER, 24, true, titles: threeTableHeadTitle);

                    for (int i = 1; i < 5; i++)
                    {
                        threeTable
                            .SetTableParagraph(i, 0, "1", ParagraphAlignment.CENTER, 80, false)
                            .SetTableParagraph(i, 1, "同意", ParagraphAlignment.CENTER, 80, false)
                            .SetTableParagraph(i, 2, "审批通过", ParagraphAlignment.CENTER, 80, false)
                            .SetTableParagraph(i, 3, "张三", ParagraphAlignment.CENTER, 80, false)
                            .SetTableParagraph(i, 4, "2020-01-01 12:23:21", ParagraphAlignment.CENTER, 80, false);
                    }
                    document.
                        SetDocumentMargin("1000", "1500", "1000", "1000")
                        .Write(stream);
                    result = "ok";
                }
            }
            catch (Exception ex)
            {
                result = ex.Message;
            }
            return result;
        }
        public static string ReadTest(string wordFilePath)
        {
            string result = "";
            Stream stream = File.OpenRead(wordFilePath);
            XWPFDocument doc = new XWPFDocument(stream);
            foreach (var para in doc.Paragraphs)
            {
                string text = para.ParagraphText; //获得文本
                if (text.Trim() != "")
                    Console.WriteLine(text);
            }
            //多个图片可以直接通过AllPictures获取
            var tab = doc.CreateTable(5, 5);//创建一个表格对象

            XWPFParagraph p = doc.CreateParagraph();//创建一个段落，在Word里直接输出如果要引用则会出现两次

            var ct = new CT_P();//

            var p1 = new XWPFParagraph(ct, tab.Body);//新建一个段落对象

            XWPFRun r = p.CreateRun();//为段落创建一个可赋值对象

            r.SetText("1");//给段落设置值
            r.AppendText("1");//给段落追加文本
            tab.GetRow(1).GetCell(1).SetParagraph(p);//为表格row行col列添加一个段落

            tab.GetRow(1).GetCell(1).SetText("空");//为表格row行col列设置一个值
            string fileName = string.Format("{0}.docx", DateTime.Now.ToString("d"), System.Text.Encoding.UTF8);
            using (var s = new FileStream(Path.Combine("D:\\", fileName), FileMode.Create, FileAccess.Write))
            {

            };
            //FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read);
           doc.Write(stream);
            return result;
        }
        #endregion
    }
}
